/**
 * Copyright (c) 2007,中企动力华南研发中心<br>
 * All rights reserved.
 */
package com.ce.pms.charge.service.impl;

import java.math.BigDecimal;
import java.util.Set;
import com.ce.pms.charge.model.AbstractStaVersion;
import com.ce.pms.charge.model.GeneralVersion;
import com.ce.pms.charge.model.MeterVersion;
import com.ce.pms.charge.model.SectSta;
import com.ce.pms.common.model.SysrefcodeDO;
import com.ce.pms.common.util.BigDecimalUtil;
import com.ce.pms.exception.BusinessException;

/**
 * 功能描述：应收计算算法类<br>
 * @author 罗军林 创建日期：2008-8-15
 */
public class ArithmeticCharge {

	private String countMode;
	private BigDecimal price;
	private Set<SectSta> secStas;


	public ArithmeticCharge(AbstractStaVersion staVersion){
		if(staVersion instanceof GeneralVersion){
			this.countMode=((GeneralVersion)staVersion).getCountMode();
		}else if(staVersion instanceof MeterVersion){
			this.countMode=((MeterVersion)staVersion).getCountMode();
		}
		this.price=staVersion.getPrice();
		this.secStas=staVersion.getSecStas();
	}

	/**
	 * 功能描述:根据既定规则计算费用<br>
	 * @param amount
	 * @return<br>
	 * Create author:罗军林<br>
	 * Create on:2008-8-15<br>
	 * Edit author:<br>
	 * Edit on:<br>
	 * Why:<br>
	 */
	public BigDecimal calculate(BigDecimal amount) {
		if(amount==null){
			throw new BusinessException("charge:amount_not_null");
		}
		return BigDecimalUtil.warpResult( calculateCore(amount) );
	}

	/**
	 * 功能描述:根据计算策略进行计算<br>
	 * @param amount
	 * @return<br>
	 * Create author:罗军林<br>
	 * Create on:2008-11-19<br>
	 * Edit author:<br>
	 * Edit on:<br>
	 * Why:<br>
	 */
	private BigDecimal calculateCore(BigDecimal amount) {
		if( SysrefcodeDO.FEE_CHARGESTA_CAST_VALUE_SINGLE.equals(getCountMode()) ){//单一
			return  calculateForSingle(amount);
		}else if( SysrefcodeDO.FEE_CHARGESTA_CAST_VALUE_LADDER.equals(getCountMode()) ){//阶梯
			return calculateForLadder(amount);
		}else if( SysrefcodeDO.FEE_CHARGESTA_CAST_VALUE_EXCESS.equals(getCountMode()) ){//超额累进
			return calculateForExcess(amount);
		}else if( SysrefcodeDO.FEE_CHARGESTA_CAST_VALUE_FASTNESS.equals(getCountMode()) ){//固定
			return calculateForFastness(amount);
		}else{
			throw new BusinessException("charge:countMode_Error");
		}
	}

	/**
	 * 功能描述:固定计费.取得该用量所在的价格<br>
	 * @return<br>
	 * Create author:罗军林<br>
	 * Create on:2008-8-14<br>
	 * Edit author:<br>
	 * Edit on:<br>
	 * Why:<br>
	 */
	private BigDecimal calculateForFastness(BigDecimal amount) {
//		return this.getPrice();
		for(SectSta sectSta : this.getSecStas()){
			if( amount.compareTo(sectSta.getStartPoint()) > 0 &&
					amount.compareTo(sectSta.getToPoint()) <= 0 ){
				return sectSta.getPrice();
			}
		}
		return new BigDecimal(0);
	}

	/**
	 * 功能描述:超额累进<br>
	 * @param amount<br>
	 * Create author:罗军林<br>
	 * Create on:2008-8-14<br>
	 * Edit author:<br>
	 * Edit on:<br>
	 * Why:<br>
	 */
	private BigDecimal calculateForExcess(BigDecimal amount) {
		BigDecimal result=new BigDecimal(0);
		for(SectSta sectSta : this.getSecStas()){
			result=result.add( calculateForSect(amount, sectSta) );
		}
		return result;
	}

	/**
	 * 功能描述:计算单个断点费用<br>
	 * @param amount
	 * @param sectSta<br>
	 * Create author:罗军林<br>
	 * Create on:2008-8-14<br>
	 * Edit author:<br>
	 * Edit on:<br>
	 * Why:<br>
	 */
	private BigDecimal calculateForSect(BigDecimal amount, SectSta sectSta) {
		if(amount==null){
			return new BigDecimal(0);
		}else if( amount.compareTo(sectSta.getStartPoint()) > 0 &&
				amount.compareTo(sectSta.getToPoint()) > 0 ){
			return sectSta.getToPoint().subtract(sectSta.getStartPoint()).multiply(sectSta.getPrice());
		}else if( amount.compareTo(sectSta.getStartPoint()) > 0 &&
				amount.compareTo(sectSta.getToPoint()) <= 0 ){
			return amount.subtract(sectSta.getStartPoint()).multiply(sectSta.getPrice());
		}else{
			return new BigDecimal(0);
		}
	}

	/**
	 * 功能描述:阶递计费<br>
	 * @param amount<br>
	 * Create author:罗军林<br>
	 * Create on:2008-8-14<br>
	 * Edit author:<br>
	 * Edit on:<br>
	 * Why:<br>
	 */
	private BigDecimal calculateForLadder(BigDecimal amount) {
		for(SectSta sectSta : this.getSecStas()){
			if( amount.compareTo(sectSta.getStartPoint()) > 0 &&
					amount.compareTo(sectSta.getToPoint()) <= 0 ){
				return amount.multiply(sectSta.getPrice());
			}
		}
		return new BigDecimal(0);
	}

	/**
	 * 功能描述:单一计费<br>
	 * @param amount
	 * @return<br>
	 * Create author:罗军林<br>
	 * Create on:2008-8-14<br>
	 * Edit author:<br>
	 * Edit on:<br>
	 * Why:<br>
	 */
	private BigDecimal calculateForSingle(BigDecimal amount) {
		return amount.multiply(this.getPrice());
	}



	public BigDecimal getPrice() {
		return price;
	}
	public Set<SectSta> getSecStas() {
		return secStas;
	}
	private String getCountMode() {
		return countMode;
	}

}
